import 'package:kq_flutter_core_widget/utils/ex/kq_ex.dart';

import 'core/executor.dart';
import 'core/group_key.dart';
import 'core/monitor.dart';

///可控制执行结束时机的执行者。
///主要用于多个接口联级调用或者链式调用等场景Loading框的控制。
///跟CombineExecutor原理类似，只是ControlExecutor可控制，
///不会自动自行完毕，需要用户主动调用stop或者给需要执行完毕的接口添加stop标记。
///可以监听多个接口联级调用、链式调用、多接混合调用出现异常和报错等监听，
///不干涉接口请求逻辑，只监听接口请求的
///成功状态（response.code == ApiResponse.success），失败状态（response.code != ApiResponse.success）,
///接口catch后的监听，以及onError监听，例如在调用一系列接口时，
///调用第一个接口之前会回调onStart,
///等调用到接口状态设置了stop=true时的接口时和中间任意一个接口接口异常或失败状态时，
///则会回调onFinish，结束本次执行。
class ControlExecutor {
  ///执行的对象保存
  final Map<GroupKey, List<Monitor>> _monitors = {};

  ///Executor 保存
  final List<Executor> _executors = [];

  final Function(GroupKey key)? onStart;
  final Function(GroupKey key)? onFinish;

  ControlExecutor({this.onStart, this.onFinish});

  ///这里的逻辑跟CombineExecutor不同。
  _executor(GroupKey key) {
    Executor executor = Executor(key);
    if (!_executors.contains(executor)) {
      _executors.add(executor);
      onStart?.call(key);

      executor.start(callback: (key) {
        List<Monitor> combines = _get(key);
        bool flag = false;
        for (Monitor monitor in combines) {
          if (monitor.isError() ||
              monitor.isFinish() && (monitor.getExtra() ?? false)) {
            flag = true;
            break;
          }
        }

        //表示最后一个都已执行完成
        if (flag) {
          executor.stop(callback: (key) {
            onFinish?.call(key);
            _clear(key);
            _executors.remove(executor);
          });
        }
      });
    }
  }

  ///停止，在退出界面时调用
  stop() {
    for (Executor executor in _executors) {
      executor.stop();
    }
    _executors.clear();
    _clearAll();
  }

  ///获取合并执行观察者，
  ///设置到请求逻辑中。
  ///[stop] 是否停止。
  Monitor getMonitor(GroupKey key, {bool? stop}) {
    Monitor monitor = Monitor(extra: stop);
    _addCombine(key, monitor);
    _executor(key);
    return monitor;
  }

  ///新增一个monitor
  _addCombine(GroupKey key, Monitor combine) {
    if (key.isMonitor) {
      if (_monitors.containsKey(key)) {
        List<Monitor>? combines = _monitors[key];
        combines ??= [];
        if (!combines.contains(combine)) {
          combines.add(combine);
        }
      } else {
        _monitors.putIfAbsent(key, () => [combine]);
      }
    }
  }

  List<Monitor> _get(GroupKey key) {
    if (_isEmpty(key)) {
      return [];
    } else {
      return _monitors[key]!;
    }
  }

  ///monitor是否为空
  _isEmpty(GroupKey key) {
    return !_monitors.containsKey(key) || _monitors[key].isNullOrEmpty;
  }

  _clear(GroupKey key) {
    _monitors.remove(key);
  }

  ///清除全部的monitor
  _clearAll() {
    _monitors.clear();
  }
}

///测试
class ControlExecutorTest {
  test() {
    ///创建一个GroupKey，改key可用于一组需要调用的接口上
    GroupKey groupKey = GroupKey();

    ///创建对象
    ControlExecutor executor = ControlExecutor(
      onStart: (key) {
        ///print("开始执行");
      },
      onFinish: (key) {
        if (key == groupKey) {
          ///print("结束执行");
        }
      },
    );

    ///获取monitor 传入到接口调用中
    Monitor monitor1 = executor.getMonitor(groupKey);
    ///获取monitor 传入到接口调用中
    Monitor monitor2 = executor.getMonitor(groupKey);
    ///获取monitor 传入到接口调用中，结束的monitor
    Monitor monitor3 = executor.getMonitor(groupKey, stop: true);

    ///模拟异步对Monitor进行操作
    Future.delayed(const Duration(seconds: 2), () {
      monitor1.onFinish();
    });
    Future.delayed(const Duration(seconds: 3), () {
      monitor2.onFinish();
    });
    Future.delayed(const Duration(seconds: 5), () {
      monitor3.onFinish();
    });

    ///退出界面
    executor.stop();
  }
}
